package com.waterworld.watch.location.fragment;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.BounceInterpolator;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.TextView;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.Projection;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.waterworld.watch.R;
import com.waterworld.watch.common.application.MyApplication;
import com.waterworld.watch.common.bean.LocationBean;
import com.waterworld.watch.common.net.BaseObserverListener;
import com.waterworld.watch.common.net.BaseResultBean;
import com.waterworld.watch.common.service.OverallService;
import com.waterworld.watch.common.util.ToastUtils;
import com.waterworld.watch.location.activity.ElectronicFenceActivity;
import com.waterworld.watch.location.activity.TrackActivity;
import com.waterworld.watch.location.interfaces.ILocationManager;
import com.waterworld.watch.location.manager.LocationManager;
import com.waterworld.watch.login.interfaces.CodeCountListener;
import com.waterworld.watch.push.event.MessageEvent;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class LocationFragment extends Fragment {

    @BindView(R.id.map)
    MapView mMapView;

    @BindView(R.id.iv_refresh)
    ImageView iv_refresh;

    @BindView(R.id.iv_navigation)
    ImageView iv_navigation;

    @BindView(R.id.iv_electronic_fence)
    ImageView iv_electronic_fence;

    @BindView(R.id.iv_change)
    ImageView iv_change;

    @BindView(R.id.iv_track)
    ImageView iv_track;

    @BindView(R.id.tv_location_address)
    TextView tv_location_address;

    @BindView(R.id.tv_location_time)
    TextView tv_location_time;

    @BindView(R.id.tv_location_type)
    TextView tv_location_type;

    @BindView(R.id.tv_location_state)
    TextView tv_location_state;

    private AMap aMap = null;
    private ILocationManager iLocationManager = LocationManager.getInstance();
    private View mRootView;

    private boolean isInGetGPSLocationMode = false;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        if (mRootView != null) {
            return mRootView;
        }
        mRootView = inflater.inflate(R.layout.fragment_position,container,false);
        ButterKnife.bind(this,mRootView);
        mMapView.onCreate(savedInstanceState);
        if(aMap == null){
            aMap = mMapView.getMap();
        }
        EventBus.getDefault().register(this);
        LocationCountListeners();
        return mRootView;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (!isInGetGPSLocationMode && isVisibleToUser) {
            isInGetGPSLocationMode = true;
            startLocation();
        }
    }

    //开始定位
    private void startLocation(){
        if (iLocationManager != null) {
           iLocationManager.getLocation(new BaseObserverListener<BaseResultBean<LocationBean>>() {
               @Override
               public void onCompleted() {
               }

               @Override
               public void onError(Throwable e) {
               }

               @Override
               public void onNext(BaseResultBean<LocationBean> baseResultBean) {
                   if (baseResultBean.getCode() != 0) {
                       isInGetGPSLocationMode = false;
                       if (baseResultBean.getData() != null) {
                           LatLng latLng = new LatLng(Double.parseDouble(baseResultBean.getData().getLat()), Double.parseDouble(baseResultBean.getData().getLng()));
                           CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(new CameraPosition(latLng, 17, 0, 0));
                           aMap.moveCamera(mCameraUpdate);
                           aMap.clear();
                           View view = getActivity().getLayoutInflater().inflate(R.layout.location_marker_view, null);
                           TextView tvLocationAccuracy = view.findViewById(R.id.tv_location_accuracy);
                           tvLocationAccuracy.setText(String.format(getString(R.string.location_accuracy), baseResultBean.getData().getAccuracy()));
                           tvLocationAccuracy.setHorizontallyScrolling(false);
                           boolean isNeedAnimation = getUserVisibleHint() && !isInGetGPSLocationMode;
                           addMarkerToMap(latLng, view, 0.5f, 0.66f, isNeedAnimation, 0);

                           tv_location_address.setText(baseResultBean.getData().getAddress());
                           tv_location_time.setText(baseResultBean.getData().getUploadTime());
                           switch (baseResultBean.getData().getLocationType()) {
                               case 0:
                                   tv_location_type.setText(" | 基站");
                                   break;
                               case 1:
                                   tv_location_type.setText(" | WIFI");
                                   break;
                               case 2:
                               tv_location_type.setText(" | GPS");
                               break;
                           }
                           tv_location_state.setText(" (手表当前未连接网络)");
                       }
                   } else if (baseResultBean.getCode() == 0) {
                       getLastLocation(" (正在定位中...)");
                       if(MyApplication.getInstance().getService() != null){
                           MyApplication.getInstance().getService().startLocateDown();
                       }
                   }
               }
           });
        }
    }

    private void getLastLocation(String tips) {
        if (iLocationManager != null) {
            iLocationManager.getLastLocation(new BaseObserverListener<BaseResultBean<LocationBean>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(BaseResultBean<LocationBean> baseResultBean) {
                    if (baseResultBean.getData() != null) {
                        LatLng latLng = new LatLng(Double.parseDouble(baseResultBean.getData().getLat()), Double.parseDouble(baseResultBean.getData().getLng()));
                        CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(new CameraPosition(latLng, 17, 0, 0));
                        aMap.moveCamera(mCameraUpdate);
                        aMap.clear();
                        View view = getActivity().getLayoutInflater().inflate(R.layout.location_marker_view, null);
                        TextView tvLocationAccuracy = view.findViewById(R.id.tv_location_accuracy);
                        tvLocationAccuracy.setText(String.format(getString(R.string.location_accuracy), baseResultBean.getData().getAccuracy()));
                        tvLocationAccuracy.setHorizontallyScrolling(false);
                        boolean isNeedAnimation = getUserVisibleHint() && !isInGetGPSLocationMode;
                        addMarkerToMap(latLng, view, 0.5f, 0.66f, isNeedAnimation, 0);

                        tv_location_address.setText(baseResultBean.getData().getAddress());
                        tv_location_time.setText(baseResultBean.getData().getUploadTime());
                        switch (baseResultBean.getData().getLocationType()) {
                            case 0:
                                tv_location_type.setText(" | 基站");
                                break;
                            case 1:
                                tv_location_type.setText(" | WIFI");
                                break;
                            case 2:
                                tv_location_type.setText(" | GPS");
                                break;
                        }
                        tv_location_state.setText(tips);
                    }
                }
            });
        }
    }

    private void LocationCountListeners(){
        if(MyApplication.getInstance().getService() != null){
            //定位后等待30s才可以重新发送
            MyApplication.getInstance().getService().setLocateDown(new CodeCountListener() {
                @Override
                public void count(int count) {
                }

                @Override
                public void complete() {
                    //定位时间到
                    isInGetGPSLocationMode = false;
                    tv_location_state.setText("手表信号差，请稍后重试!");
                }
            });
        }
    }

    @OnClick(R.id.iv_refresh)
    void onRefresh() {
        if (!isInGetGPSLocationMode) {
            startLocation();
        }
    }

    @OnClick(R.id.iv_electronic_fence)
    void onElectonicFence(){
        startActivity(new Intent(this.getContext(), ElectronicFenceActivity.class));
    }

    @OnClick(R.id.iv_track)
    void onTrack() {
        startActivity(new Intent(this.getContext(), TrackActivity.class));
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);
    }


    public Object addMarkerToMap(LatLng latLng, View view, float anchorX, float anchorY, boolean isNeedAnimation, long displayTime) {
        Object marker = null;
        if (latLng != null && aMap != null) {
            aMap.moveCamera(CameraUpdateFactory.changeLatLng(latLng));
            BitmapDescriptor bitmapDesAmap = BitmapDescriptorFactory.fromView(view);
            marker = aMap.addMarker(new MarkerOptions().position(latLng).icon(bitmapDesAmap).anchor(anchorX, anchorY).draggable(false));
            if (isNeedAnimation) {
                jump(latLng.latitude, latLng.longitude, marker);
            }
            if (displayTime > 0) {
                removeMarkerDelay(marker, displayTime);
            }
        }
        return marker;
    }

    private void removeMarkerDelay(final Object marker, long displayTime) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (marker instanceof Marker) {
                    ((Marker) marker).remove();
                }
            }
        }, displayTime);
    }

    private void jump(final double lat, final double lng, final Object marker) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final long duration = 1500;
        final Interpolator interpolator = new BounceInterpolator();

        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed / duration);
                if (aMap == null) {
                    return;
                }
                LatLng latLngAmap = new LatLng(lat, lng);
                Projection projAmap = aMap.getProjection();
                if (projAmap != null) {
                    Point startPointAmap = projAmap.toScreenLocation(latLngAmap);
                    startPointAmap.offset(0, -100);
                    LatLng startLatLngAmap = projAmap.fromScreenLocation(startPointAmap);
                    double latAmap = t * latLngAmap.latitude + (1 - t)
                            * startLatLngAmap.latitude;
                    double lngAmap = t * latLngAmap.longitude + (1 - t)
                            * startLatLngAmap.longitude;
                    if (marker instanceof Marker) {
                        ((Marker) marker).setPosition(new LatLng(latAmap, lngAmap));
                    }
                }
                if (t < 1.0) {
                    handler.postDelayed(this, 16);
                }
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getLocationSucess(MessageEvent event) {
        if (event.getType() == 2) {
            getLastLocation(" （定位成功）");
            isInGetGPSLocationMode = false;
            OverallService.hasLocated = true;
        }
    }

}
